package effectiveJava.reflect.proxy.ProxyDecorate;

import effectiveJava.reflect.proxy.ProxyDecorate.base.*;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

public class DecorateAnimal implements Animal {

    //todo 被包装的动物
    private Animal animal;
    //todo 包装器
    private Class<? extends Feature> clazz;

    public DecorateAnimal(Animal _animal, Class<? extends Feature> _clazz) {
        this.animal = _animal;
        this.clazz = _clazz;
    }

    @Override
    public void doStuff() {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object o = null;
                if (Modifier.isPublic(method.getModifiers()))
                    o = method.invoke(clazz.newInstance(), args);
                animal.doStuff();
                return o;
            }
        };
        //todo 当前类 加载器
        ClassLoader loader = getClass().getClassLoader();
        //todo 动态代理，由handler决定如何包装
        Feature proxy = (Feature) Proxy.newProxyInstance(loader, clazz.getInterfaces(), handler);
        proxy.load();
    }

    public static void main(String[] args) {
        Animal jerry = new Rat();
        jerry = new DecorateAnimal(jerry, FlyFeature.class);
        jerry = new DecorateAnimal(jerry, DigFeature.class);
        /*todo 之所以先打印 dig 然后 fly， doStuff 这种效果是因为 第一次 new DecorateAnimal()是 jerry还是一个 Rat，但是第二次已经是一个带有(animal 为 Rat, clazz为FlyFeature)的DecorateAnimal,生成一个(animal 为DecorateAnimal，clazz为DigFeature)的DecorateAnimal
        * todo 在第三十行调用animal.doStuff() 时实际调用的是 DecorateAnimal的doStuff()，其又会调用 fly以及真正的doStuff()*/
        jerry.doStuff();
    }
        //todo 个人定义：包装的重入？层级？递归？
}
